/// File:		Camera.h
/// Author:		Dennis Norton
/// Date:		04/15/12
/// Purpose:	This class makes up what would be the game's camera.

#ifndef CAMERA_H_
#define CAMERA_H_

#include "Frame.h"
#include "../../Norton Engine/Utilities/Timer.h"
#include <queue>


struct Frustum
{
	D3DXPLANE Planes[6];
	D3DXVECTOR3 CornerPoint[8];

	bool IsPointInsideFrustum(const D3DXVECTOR3& Point);
	bool IsRectInsideFrustum(const D3DXVECTOR3& Point, const float& Width, const float& Height);
	void MakePlane(int index, const D3DXVECTOR3& PointA, const D3DXVECTOR3& PointB, const D3DXVECTOR3& PointC);
};

class RenderObject;
class Camera
{
public:
	enum CAMERAMODE {CM_HardAttach, CM_HardLerp, CM_SoftAttach, CM_FirstPerson, CM_ThirdPerson, CM_Input, CM_DoNothing, CM_MAX};
	enum FRUSTUMPLANE {FP_Left, FP_Right, FP_Near, FP_Far, FP_Top, FP_Bottom, FP_MAX};
	enum FRUSTUMCORNER {FC_NTR, FC_NBR, FC_NBL, FC_NTL, FC_FTR, FC_FTL, FC_FBL, FC_FBR, FC_MAX};
private:
	// Stores all the matrix data associated with the camera.
	Frame* _CameraFrame;
	bool _IsPerspective;
	D3DXMATRIX _Proj, _Ortho;
	D3DVIEWPORT9 _ViewPort;
	float _FOV, _NearPlane, _FarPlane, _AspectRatio;

	Frustum* _ViewFrustum;
	Timer _StopWatch;
	std::queue<D3DXVECTOR3> _QueuedPositons;
	unsigned char _MaxQueueCount;
	bool _Transition;
	CAMERAMODE _Mode;
	float _TransitionTime;

	// Private functions
	void _DoSoftAttach(float delta);
	void _DoHardAttach(float delta);
	void _DoHardLerp(float delta);
	void _DoInput(float delta);
	void _DoFirstPerson(float delta);
	void _DoThirdPerson(float delta);
	void _LerpToPosition(D3DXVECTOR3& Pos, float delta);
public:
	Camera();
	~Camera();

	void CreateViewMatrix(D3DXVECTOR3& Position, D3DXVECTOR3& LookingAt, D3DXVECTOR3& WorldUp);
	void MakePerspective(float FOV, float AspectRatio, float NearPlane, float FarPlane);
	void MakeOrthographic(float Width, float Height, float Near, float Far);

	void UpdateViewport(int X, int Y, int Width, int Height);

	void Update(float delta);
	//bool IsPointInsideFrustum(const D3DXVECTOR3& Point);
	void BuildFrustum();

	/// Grabs the camera's world matrix.
	const D3DXMATRIX& GetWorldMatrix();
	/// Grabs the camera's View matrix.
	D3DXMATRIX GetViewMatrix();
	/// Grabs the camera's View matrix.
	const D3DXMATRIX& GetProjectionMatrix();

	/// Returns a pointer to the camera's frame.
	Frame* GetCameraFrame();

	inline D3DVIEWPORT9& GetViewPort() {return _ViewPort;}
	inline void ChangeCameraMode(CAMERAMODE Mode) {_Mode = Mode;}
	inline void SetPerspective(bool persp) { _IsPerspective = persp; }
	inline Frustum* GetViewFrustum() {return _ViewFrustum;}
	void ResetCamera();
};

#endif